using IngameDebugConsole;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public partial class Startup : MonoBehaviour
{
    private const string VERSION = "1";
    public static string ManifestRoot;
    [Header("内置显示节点")]
    public GameObject Node;
    public string EntryAssemblyName;
    public string EntryClassType;
    public string EntryMethod;
    [Header("模拟加载")]
    public string RemoteLoadPath;
    private Assembly entry;
    private int debugCount = 0;
    private LoadProgress LoadProgress;
    private void Start()
    {
        this.StartCoroutine(Load());
    }
    private IEnumerator Load()
    {
        DebugLogManager.Instance.PopupEnabled = false;
        DebugLogConsole.AddCommand<string, string>("set", "添加设置", setPlayerPrefs);
        DebugLogConsole.AddCommand<string>("remove", "删除设置", removePlayerPrefs);
        Dictionary<string, string> param = new Dictionary<string, string>();
        var manifestFile = "manifest.json";
        var lang = Application.systemLanguage.ToString();
        if (PlayerPrefs.HasKey("Debug"))
        {
            manifestFile = "debug.json";
        }
        param.Add("lang", lang);
        string guid;
        if (PlayerPrefs.HasKey("PlayerGUID"))
        {
            guid = PlayerPrefs.GetString("PlayerGUID");
            if (string.IsNullOrEmpty(guid))
            {
                guid = System.Guid.NewGuid().ToString();
                PlayerPrefs.SetString("PlayerGUID", guid);
            }
        }
        else
        {
            guid = System.Guid.NewGuid().ToString();
            PlayerPrefs.SetString("PlayerGUID", guid);
        }
        param.Add("version", Application.version);
        param.Add("platform", Application.platform.ToString());
        param.Add("guid", guid);
        if (Node != null)
        {
            this.LoadProgress = Node.AddComponent<LoadProgress>();
        }
        setProgress(0f);
        bool isEditor = false;
#if UNITY_EDITOR
        isEditor = true;
#endif
        string AssemblyPath = string.Empty;
        string AssetBundlePath = string.Empty;
        if (!string.IsNullOrEmpty(ManifestRoot))
        {
            string remoteUrl = ManifestRoot;
            if (PlayerPrefs.HasKey("cdnurl"))
            {
                remoteUrl = PlayerPrefs.GetString("cdnurl");
            }
            //如果没有服务器则要用 模式 和 语言 获取资源路径
            if (!string.IsNullOrEmpty(remoteUrl))
            {
                var url = Path.Combine(remoteUrl, Application.platform.ToString());
                var manifestPath = new System.Uri(Path.Combine(url, manifestFile)).AbsoluteUri + "?" + UnityEngine.Random.Range(9999999, 99999999) + "_" + (DateTime.Now.Ticks);
                Debug.Log(manifestPath);
                int retryCount = 3;
                while (retryCount-- > 0)
                {
                    Debug.LogFormat("SendWebRequest count {0}", 5 - retryCount);
                    var request = UnityWebRequest.Get(manifestPath);
                    request.timeout = 10;
                    yield return request.SendWebRequest();
                    if (request.result == UnityWebRequest.Result.Success)
                    {
                        try
                        {
                            var manifestJson = JsonUtility.FromJson<ManifestJson>(request.downloadHandler.text);
                            AssemblyPath = manifestJson.Assembly;
                            AssetBundlePath = manifestJson.AssetBundle;
                            retryCount = -1;
                        }
                        catch (Exception)
                        {

                            throw;
                        }
                    }
                    else
                    {
                        //苹果第一次请求可能不成功
                        yield return new WaitForSeconds(0.2f);
                    }
                }
            }
            else
            {
                setProgress(1f);
            }
        }

        Debug.LogFormat("AssemblyPath {0}", AssemblyPath);
        Debug.LogFormat("AssetBundlePath {0}", AssetBundlePath);
        var loader = new HotfixLoader(AssemblyPath);
        loader.OnProgress = () =>
        {
            setProgress(loader.Progress);
        };
        yield return loader.Load(EntryAssemblyName, isEditor);
        entry = loader.HotfixAssembly;
        if (entry != null)
        {
            var appType = entry.GetType(EntryClassType);
            var mainMethod = appType.GetMethod(EntryMethod);
            PlayerPrefs.SetString("RemoteLoadPath", RemoteLoadPath);
            Debug.Log("enter");
            mainMethod.Invoke(null, new object[] { this.Node, AssetBundlePath });
        }
        else
        {
            Debug.LogError("没有找到入口程序集");
        }
        setProgress(1f);
    }
    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            if (Input.mousePosition.x > 0.8f * Screen.width && Input.mousePosition.y > 0.8f * Screen.height)
            {
                debugCount++;
                if (debugCount > 10)
                {
                    DebugLogManager.Instance.PopupEnabled = true;
                }
            }
            else
            {
                debugCount = 0;
            }
        }
    }
    private void setProgress(float value)
    {
        if (LoadProgress != null)
        {
            LoadProgress.Value = value;
        }
    }
    private void setPlayerPrefs(string key, string value)
    {
        var k = key.Trim();
        if (string.IsNullOrEmpty(k))
        {
            return;
        }
        var v = value.Trim();
        if (string.IsNullOrEmpty(v))
        {
            Debug.LogWarning("删除设置" + key);
            PlayerPrefs.DeleteKey(k);
        }
        else
        {
            Debug.LogWarning("添加设置" + key + " : " + v);
            PlayerPrefs.SetString(k, v);
        }

    }
    private void removePlayerPrefs(string key)
    {
        var k = key.Trim();
        if (string.IsNullOrEmpty(k))
        {
            return;
        }
        Debug.LogWarning("删除设置" + key);
        PlayerPrefs.DeleteKey(k);

    }
}

public class ManifestJson
{
    public string Assembly;
    public string AssetBundle;
}
internal class LoadProgress : MonoBehaviour
{
    public float Value;
    private Image progressImg;
    private void Awake()
    {
        var img = this.transform.Find("progress");
        if (img != null)
        {
            progressImg = img.GetComponent<Image>();
        }
    }
    private void Update()
    {
        if (progressImg != null)
        {
            progressImg.fillAmount = Mathf.Lerp(progressImg.fillAmount, Value, 0.1f);
        }
    }
}